home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-9.10-netbook-remix-PL.iso / casper / filesystem.squashfs / usr / share / pyshared / louie / saferef.py < prev    next >
Text File  |  2005-12-06  |  7KB  |  180 lines

  1. """Refactored 'safe reference from dispatcher.py"""
  2.  
  3. import weakref
  4. import traceback
  5.  
  6.  
  7. def safe_ref(target, on_delete=None):
  8.     """Return a *safe* weak reference to a callable target.
  9.  
  10.     - ``target``: The object to be weakly referenced, if it's a bound
  11.       method reference, will create a BoundMethodWeakref, otherwise
  12.       creates a simple weakref.
  13.         
  14.     - ``on_delete``: If provided, will have a hard reference stored to
  15.       the callable to be called after the safe reference goes out of
  16.       scope with the reference object, (either a weakref or a
  17.       BoundMethodWeakref) as argument.
  18.     """
  19.     if hasattr(target, 'im_self'):
  20.         if target.im_self is not None:
  21.             # Turn a bound method into a BoundMethodWeakref instance.
  22.             # Keep track of these instances for lookup by disconnect().
  23.             assert hasattr(target, 'im_func'), (
  24.                 "safe_ref target %r has im_self, but no im_func, "
  25.                 "don't know how to create reference"
  26.                 % target
  27.                 )
  28.             reference = BoundMethodWeakref(target=target, on_delete=on_delete)
  29.             return reference
  30.     if callable(on_delete):
  31.         return weakref.ref(target, on_delete)
  32.     else:
  33.         return weakref.ref(target)
  34.     
  35.  
  36. class BoundMethodWeakref(object):
  37.     """'Safe' and reusable weak references to instance methods.
  38.  
  39.     BoundMethodWeakref objects provide a mechanism for referencing a
  40.     bound method without requiring that the method object itself
  41.     (which is normally a transient object) is kept alive.  Instead,
  42.     the BoundMethodWeakref object keeps weak references to both the
  43.     object and the function which together define the instance method.
  44.  
  45.     Attributes:
  46.     
  47.     - ``key``: The identity key for the reference, calculated by the
  48.       class's calculate_key method applied to the target instance method.
  49.  
  50.     - ``deletion_methods``: Sequence of callable objects taking single
  51.       argument, a reference to this object which will be called when
  52.       *either* the target object or target function is garbage
  53.       collected (i.e. when this object becomes invalid).  These are
  54.       specified as the on_delete parameters of safe_ref calls.
  55.  
  56.     - ``weak_self``: Weak reference to the target object.
  57.  
  58.     - ``weak_func``: Weak reference to the target function.
  59.  
  60.     Class Attributes:
  61.         
  62.     - ``_all_instances``: Class attribute pointing to all live
  63.       BoundMethodWeakref objects indexed by the class's
  64.       calculate_key(target) method applied to the target objects.
  65.       This weak value dictionary is used to short-circuit creation so
  66.       that multiple references to the same (object, function) pair
  67.       produce the same BoundMethodWeakref instance.
  68.     """
  69.     
  70.     _all_instances = weakref.WeakValueDictionary()
  71.     
  72.     def __new__(cls, target, on_delete=None, *arguments, **named):
  73.         """Create new instance or return current instance.
  74.  
  75.         Basically this method of construction allows us to
  76.         short-circuit creation of references to already- referenced
  77.         instance methods.  The key corresponding to the target is
  78.         calculated, and if there is already an existing reference,
  79.         that is returned, with its deletion_methods attribute updated.
  80.         Otherwise the new instance is created and registered in the
  81.         table of already-referenced methods.
  82.         """
  83.         key = cls.calculate_key(target)
  84.         current = cls._all_instances.get(key)
  85.         if current is not None:
  86.             current.deletion_methods.append(on_delete)
  87.             return current
  88.         else:
  89.             base = super(BoundMethodWeakref, cls).__new__(cls)
  90.             cls._all_instances[key] = base
  91.             base.__init__(target, on_delete, *arguments, **named)
  92.             return base
  93.  
  94.     def __init__(self, target, on_delete=None):
  95.         """Return a weak-reference-like instance for a bound method.
  96.  
  97.         - ``target``: The instance-method target for the weak reference,
  98.           must have im_self and im_func attributes and be
  99.           reconstructable via the following, which is true of built-in
  100.           instance methods::
  101.             
  102.             target.im_func.__get__( target.im_self )
  103.  
  104.         - ``on_delete``: Optional callback which will be called when
  105.           this weak reference ceases to be valid (i.e. either the
  106.           object or the function is garbage collected).  Should take a
  107.           single argument, which will be passed a pointer to this
  108.           object.
  109.         """
  110.         def remove(weak, self=self):
  111.             """Set self.isDead to True when method or instance is destroyed."""
  112.             methods = self.deletion_methods[:]
  113.             del self.deletion_methods[:]
  114.             try:
  115.                 del self.__class__._all_instances[self.key]
  116.             except KeyError:
  117.                 pass
  118.             for function in methods:
  119.                 try:
  120.                     if callable(function):
  121.                         function(self)
  122.                 except Exception:
  123.                     try:
  124.                         traceback.print_exc()
  125.                     except AttributeError, e:
  126.                         print ('Exception during saferef %s '
  127.                                'cleanup function %s: %s' % (self, function, e))
  128.         self.deletion_methods = [on_delete]
  129.         self.key = self.calculate_key(target)
  130.         self.weak_self = weakref.ref(target.im_self, remove)
  131.         self.weak_func = weakref.ref(target.im_func, remove)
  132.         self.self_name = str(target.im_self)
  133.         self.func_name = str(target.im_func.__name__)
  134.         
  135.     def calculate_key(cls, target):
  136.         """Calculate the reference key for this reference.
  137.  
  138.         Currently this is a two-tuple of the id()'s of the target
  139.         object and the target function respectively.
  140.         """
  141.         return (id(target.im_self), id(target.im_func))
  142.     calculate_key = classmethod(calculate_key)
  143.     
  144.     def __str__(self):
  145.         """Give a friendly representation of the object."""
  146.         return "%s(%s.%s)" % (
  147.             self.__class__.__name__,
  148.             self.self_name,
  149.             self.func_name,
  150.             )
  151.     
  152.     __repr__ = __str__
  153.     
  154.     def __nonzero__(self):
  155.         """Whether we are still a valid reference."""
  156.         return self() is not None
  157.  
  158.     def __cmp__(self, other):
  159.         """Compare with another reference."""
  160.         if not isinstance(other, self.__class__):
  161.             return cmp(self.__class__, type(other))
  162.         return cmp(self.key, other.key)
  163.  
  164.     def __call__(self):
  165.         """Return a strong reference to the bound method.
  166.  
  167.         If the target cannot be retrieved, then will return None,
  168.         otherwise returns a bound instance method for our object and
  169.         function.
  170.  
  171.         Note: You may call this method any number of times, as it does
  172.         not invalidate the reference.
  173.         """
  174.         target = self.weak_self()
  175.         if target is not None:
  176.             function = self.weak_func()
  177.             if function is not None:
  178.                 return function.__get__(target)
  179.         return None
  180.